﻿using IDbConnectionExtend;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;

namespace IDbConnectionExtend
{
    public static class IDbConnectionExtend
    {
        private static Dictionary<Type, object> dicReaderGetterForType;
        private static Dictionary<Type, object> dicRowGetterForType;
        private static object funLock;
        static IDbConnectionExtend()
        {
            dicReaderGetterForType = new Dictionary<Type, object>();
            dicRowGetterForType = new Dictionary<Type, object>();
            funLock = new object();
        }

        /// <summary>
        /// 新增一条记录
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="con"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static int Add<T>(this IDbConnection con, T t)
        {
            return con.Execute(ModelCache<T>._AddSql, t); ;
        }
        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="con"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static int Delete<T>(this IDbConnection con, int id)
        {
            return con.Execute(ModelCache<T>._DeleteSql, new { ID = id });
        }
        /// <summary>
        /// 更新一条记录
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="con"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static int Update<T>(this IDbConnection con, T t)
        {
            return con.Execute(ModelCache<T>._UpdateSql, t);
        }
        /// <summary>
        /// 查找一条记录
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="con"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static T Find<T>(this IDbConnection con, int id)
        {
            return con.Query<T>(ModelCache<T>._FindSql, new { ID = id }).FirstOrDefault();
        }

        /// <summary>
        /// 获取所有记录
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="con"></param>
        /// <param name=""></param>
        /// <returns></returns>
        public static IEnumerable<T> GetAll<T>(this IDbConnection con)
        {
            return con.Query<T>(ModelCache<T>._GetAllSql, null);
        }

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="con"></param>
        /// <returns></returns>
        public static int Count<T>(this IDbConnection con)
        {
            var sql = string.Format("select count(*) from {0}", ModelCache<T>._TableName);
            return con.Execute<int>(sql);
        }

        /// <summary>
        /// 执行非查询语句或者查询单个结果的语句
        /// </summary>
        /// <typeparam name="T">模型类型</typeparam>
        /// <param name="con">连接字符串</param>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="defaultValue">获取异常的默认返回值</param>
        /// <returns></returns>
        public static T Execute<T>(this IDbConnection con, string sql, object param = null,  IEnumerable<IDataParameter> parameters = null, T defaultValue = default(T))
        {

            return BaseExecute<T>(con, sql, param, parameters, _cmd =>
            {
                try
                {
                    var value = _cmd.ExecuteScalar();
                    return (T)Convert.ChangeType(value, typeof(T));
                }
                catch (Exception ex)
                {
                    return defaultValue;
                }
            });
        }


        /// <summary>
        /// 执行返回影响的行数
        /// </summary>
        /// <param name="con"></param>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static int Execute(this IDbConnection con, string sql, object param = null,  IEnumerable<IDataParameter> parameters = null)
        {
            return BaseExecute<int>(con, sql, param, parameters, _cmd =>
            {
                return _cmd.ExecuteNonQuery();
            });
        }


        /// <summary>
        /// 执行非查询语句或者查询单个结果的语句
        /// </summary>
        /// <typeparam name="T">模型类型</typeparam>
        /// <param name="con">连接字符串</param>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="defaultValue">获取异常的默认返回值</param>
        /// <returns></returns>
        public static T ExecuteWithReader<T>(this IDbConnection con, string sql, object param = null,  IEnumerable<IDataParameter> parameters = null, T defaultValue = default(T))
        {

            return ExecuteReader<T>(con, sql, param, parameters, reader =>
            {
                try
                {
                    var value = reader[0];
                    return (T)Convert.ChangeType(value, typeof(T));
                }
                catch (Exception ex)
                {
                    return defaultValue;
                }
            });
        }


        /// <summary>
        /// 查询语句
        /// </summary>
        /// <typeparam name="T">模型类型</typeparam>
        /// <param name="con">连接字符串</param>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public static List<T> Query<T>(this IDbConnection con, string sql, object param = null,  IEnumerable<IDataParameter> parameters = null)
        {
            return ExecuteReader<List<T>>(con, sql, param, parameters, reader =>
            {
                return ToList<T>(reader);
            });
        }


        /// <summary>
        /// 执行reader查询
        /// </summary>
        /// <typeparam name="T">模型类型</typeparam>
        /// <param name="con">连接字符串</param>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="funcReader">reader扩展委托</param>
        /// <returns></returns>
        public static T ExecuteReader<T>(this IDbConnection con, string sql, object param,  IEnumerable<IDataParameter> parameters, Func<IDataReader, T> funcReader)
        {
            return BaseExecute<T>(con, sql, param, parameters, cmd =>
            {
                using (var reader = cmd.ExecuteReader())
                {
                    return funcReader != null ? funcReader(reader) : default(T);
                }
            });
        }

        /// <summary>
        /// dataset 结果集
        /// </summary>
        /// <typeparam name="T">模型类型</typeparam>
        /// <param name="con">连接字符串</param>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="funcDataSet">结果集查询委托</param>
        /// <returns></returns>
        public static T ExecuteDataSet<T>(this IDbConnection con, string sql, object param,  IEnumerable<IDataParameter> parameters, DbDataAdapter dataAdapter, Func<DataSet, T> funcDataSet)
        {
            if (dataAdapter == null) throw new Exception("dataAdapter can not be null!");

            return BaseExecute<T>(con, sql, param, parameters, _cmd =>
            {
                ((IDbDataAdapter)dataAdapter).SelectCommand = _cmd;
                var dataSet = new DataSet();
                dataAdapter.Fill(dataSet);
                return funcDataSet != null ? funcDataSet(dataSet) : default(T);
            });
        }



        /// <summary>
        /// dataset 结果集
        /// </summary>
        /// <typeparam name="T">模型类型</typeparam>
        /// <param name="con">连接字符串</param>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="funcDataSet">结果集查询委托</param>
        /// <returns></returns>
        public static T ExecuteDataTable<T>(this IDbConnection con, string sql, object param,  IEnumerable<IDataParameter> parameters, DbDataAdapter dataAdapter, Func<DataTable, T> funcDataTable)
        {
            return ExecuteDataSet<T>(con, sql, param, parameters, dataAdapter, dataSet =>
            {
                return funcDataTable != null ? funcDataTable(dataSet.Tables[0]) : default(T);

            });
        }



        /// <summary>
        ///  datatable结果集
        /// </summary>
        /// <param name="con">连接字符串</param>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public static DataTable ExecuteDataTable(this IDbConnection con, string sql, DbDataAdapter dataAdapter, object param = null,  IEnumerable<IDataParameter> parameters = null)
        {
            return ExecuteDataTable<DataTable>(con, sql, param, parameters, dataAdapter, table => table);
        }

        /// <summary>
        /// 基础查询方法
        /// </summary>
        /// <typeparam name="T">模型类型</typeparam>
        /// <param name="con">连接字符串</param>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="funcCmd">command 委托</param>
        /// <returns></returns>
        public static T BaseExecute<T>(this IDbConnection con, string sql, object param,  IEnumerable<IDataParameter> parameters, Func<IDbCommand, T> funcCmd)
        {
            /*
             * 如果用户先 open 再进来，我们不主动关闭链接，避免频繁打开链接（connection 有连接池控制，应该不会关这么快）
             * 如果用户进来没打开链接，由我们打开的链接，我们主动关闭
             */

            if (con.State != System.Data.ConnectionState.Open)
            {
                using (con)
                {
                    con.Open();
                    using (var cmd = con.CreateCommand())
                    {
                        return cmd.BaseExecute<T>(sql, param, parameters, funcCmd);
                    }
                }
            }
            else
            {
                using (var cmd = con.CreateCommand())
                {
                    return cmd.BaseExecute<T>(sql, param, parameters, funcCmd);
                }
            }

        }
        /// <summary>
        /// 查询执行的方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cmd"></param>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="parameters"></param>
        /// <param name="funcCmd"></param>
        /// <returns></returns>
        private static T BaseExecute<T>(this IDbCommand cmd, string sql, object param,  IEnumerable<IDataParameter> parameters, Func<IDbCommand, T> funcCmd)
        {
            cmd.CommandText = sql;
            if (param != null)
            {
                ObjectToParameter(cmd.CreateParameter().GetType(), param, cmd.Parameters);
            }
            if (parameters != null && parameters.Count() > 0)
            {
                foreach (var item in parameters)
                {
                    cmd.Parameters.Add(item);
                }
            }
            //cmd.Parameters.AddRange(paramArr.ToArray());

            var t = funcCmd != null ? funcCmd(cmd) : default(T);
            return t;
        }


        public static List<T> ToList<T>(this DataTable tb)
    {
        var tempList = new List<T>();
        if (tb != null && tb.Rows.Count > 0)
        {
            
            foreach (DataRow row in tb.Rows)
            {
                if (typeof(T).FullName.Contains("System."))
                    tempList.Add(Helper.GetDataRowValueByIndex<T>(row, 0));
                else
                {
                    dynamic getter = GetRowValueGetter<T>();
                    tempList.Add(getter.GetValue(row));
                }
            }
        }
        return tempList;
    }

    public static List<T> ToList<T>(this IDataReader reader)
    {
        var tempList = new List<T>();
        
        while (reader.Read())
        {
            if (typeof(T).FullName.Contains("System."))
                tempList.Add(Helper.GetReaderValueByIndex<T>(reader, 0));
            else
            {
                dynamic getValue = GetReaderValueGetter<T>();
                tempList.Add(getValue.GetValue(reader));
            }
        }
        return tempList;
    }


        /// <summary>
        /// 参数对象转 参数集
        /// </summary>
        /// <param name="ptType"></param>
        /// <param name="param"></param>
        /// <param name="Parameters"></param>
        private static void ObjectToParameter(Type ptType, object param, IDataParameterCollection Parameters)
        {
            if (param == null) return;
            var type = param.GetType();
            var properties = type.GetProperties();

            foreach (var property in properties)
            {
                var key = string.Format("@{0}", property.Name);
                var value = property.GetValue(param, null) ?? "";
                var t = Activator.CreateInstance(ptType, new object[] { key, value });
                if (Parameters.Contains(key))
                    Parameters[key] = value;
                else
                    Parameters.Add(t);
            }
        }

        

        /// <summary>
        /// 获取赋值委托
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private static object GetReaderValueGetter<T>()
        {
            if (!dicReaderGetterForType.ContainsKey(typeof(T)))
            {
                lock (funLock)
                {
                    if (!dicReaderGetterForType.ContainsKey(typeof(T)))
                    {
                        var type = AssemblyMaker.MakeDataReaderGetter<T>();
                        var builder = Activator.CreateInstance(type);
                        dicReaderGetterForType.Add(typeof(T), builder);
                    }
                    return dicReaderGetterForType[typeof(T)];
                }
            }
            return dicReaderGetterForType[typeof(T)];
        }

        private static object GetRowValueGetter<T>()
        {
            if (!dicRowGetterForType.ContainsKey(typeof(T)))
            {
                lock (funLock)
                {
                    if (!dicRowGetterForType.ContainsKey(typeof(T)))
                    {
                        var type = AssemblyMaker.MakeDataRowGetter<T>();
                        var builder = Activator.CreateInstance(type);
                        dicRowGetterForType.Add(typeof(T), builder);
                    }
                    return dicRowGetterForType[typeof(T)];
                }
            }
            return dicReaderGetterForType[typeof(T)];
        }

    }

    public class Helper
    {
        public static T GetReaderValueByKey<T>(IDataReader reader, string name)
        {
            try
            {
                object value = reader[name];
                if (value is DBNull)
                    return default;
                else
                {
                    return (T)value;
                }
                    
            }
            catch (Exception)
            {
                return default;
            }
        }
        public static T GetReaderValueByIndex<T>(IDataReader reader, int index)
        {
            try
            {
                object value = reader[index];
                if (value is DBNull)
                    return default;
                else
                    return (T)value;
            }
            catch (Exception)
            {
                return default;
            }
        }

        public static T GetDataRowValueByKey<T>(DataRow row, string key)
        {
            try
            {
                object value = row[key];
                if (value is DBNull)
                    return default;
                else
                    value = Convert.ChangeType(value, typeof(T));
                return (T)value;
            }
            catch (Exception)
            {
                return default;
            }
        }

        public static T GetDataRowValueByIndex<T>(DataRow row, int index)
        {
            try
            {
                object value = row[index];
                if (value is DBNull)
                    return default;
                else
                    value = Convert.ChangeType(value, typeof(T));
                return (T)value;
            }
            catch (Exception)
            {
                return default;
            }
        }
    }

    internal class AssemblyMaker
    {
        public static Type MakeDataRowGetter<T>()
        {
            return Make<T, DataRow>();
        }
        public static Type MakeDataReaderGetter<T>()
        {
            return Make<T,IDataReader>();
        }
        private static Type Make<T,SourceType>() 
        {
            var assembly = new AssemblyName("SetValueDemo_" + typeof(T).FullName);
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.RunAndSave);

            var moduleBuilder = assemblyBuilder.DefineDynamicModule("Demo", "SetValue.dll");

            var typeBuilder = moduleBuilder.DefineType("SetValue_" + typeof(T).FullName, TypeAttributes.Public);


            MakeGetValueFromReaderMethod<T, SourceType>(typeBuilder, typeof(SourceType) is IDataReader? typeof(Helper).GetMethod("GetReaderValueByKey"): typeof(Helper).GetMethod("GetDataRowValueByKey"));

            typeBuilder.CreateType();
            //assemblyBuilder.Save("SetValueDemo_" + typeof(T).FullName);
            return typeBuilder;
        }


        private static void MakeGetValueFromReaderMethod<T, SourceType>(TypeBuilder typeBuilder, MethodInfo getValueMethod)
        {
            var methodBuilder = typeBuilder.DefineMethod("GetValue", MethodAttributes.Public);
            var inputType = typeof(SourceType);
            methodBuilder.SetParameters(inputType);
            var returnType = typeof(T);
            methodBuilder.SetReturnType(returnType);


            var il = methodBuilder.GetILGenerator();
            var lable_ret = il.DefineLabel();

            il.DeclareLocal(returnType);

            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Newobj, returnType.GetConstructor(new Type[] { }));

            foreach (PropertyInfo property in returnType.GetProperties())
            {
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldstr, property.Name);
                var getGUIDValue = getValueMethod.MakeGenericMethod(new Type[] { property.PropertyType });
                il.Emit(OpCodes.Call, getGUIDValue);
                il.Emit(OpCodes.Callvirt, returnType.GetMethod("set_" + property.Name, new Type[] { property.PropertyType }));
                il.Emit(OpCodes.Nop);
            }

            il.Emit(OpCodes.Stloc_0);
            il.Emit(OpCodes.Br, lable_ret);


            il.MarkLabel(lable_ret);
            il.Emit(OpCodes.Ldloc_0);
            il.Emit(OpCodes.Ret);
        }
    }

    public interface IUnitWorker : IDisposable
    {
        /// <summary>
        /// 数据链接
        /// </summary>
        IDbConnection DbConnection { get; }
        /// <summary>
        /// 开启事务
        /// 如果初始化时默认开启事务，则无需再次开启
        /// </summary>
        void BeginTransaction();
        /// <summary>
        /// 提交事务
        /// </summary>
        void Commit();
        /// <summary>
        /// 回滚事务
        /// </summary>
        void Rollback();
    }

    /// <summary>
    /// 模型缓存，第一次用到某个模型时进行属性缓存，下次再用到时将不再重新反射
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ModelCache<T>
    {

        /// <summary>
        /// 插入sql
        /// </summary>
        public static string _AddSql = null;
        /// <summary>
        /// 更新sql
        /// </summary>
        public static string _UpdateSql = null;
        /// <summary>
        /// 删除sql
        /// </summary>
        public static string _DeleteSql = null;
        /// <summary>
        /// 查询sql
        /// </summary>
        public static string _FindSql = null;
        /// <summary>
        /// 获取所有列表的sql
        /// </summary>
        public static string _GetAllSql = null;
        /// <summary>
        /// 选择的字段，只列出字段
        /// </summary>
        public static string _SelectFields = null;

        /// <summary>
        /// 属性和真实字段映射
        /// </summary>
        public static Dictionary<string, string> _DicPropertyField = null;
        /// <summary>
        /// 真实字段和属性映射
        /// </summary>
        public static Dictionary<string, string> _DicFieldProperty = null;
        /// <summary>
        /// 主键 默认为 ：ID
        /// </summary>
        public static string _PrimaryKey = "ID".ToUpper();
        public static string _TableName = null;
        /// <summary>
        /// 属性列表
        /// </summary>
        public static PropertyInfo[] _Properties = null;


        static ModelCache()
        {
            //初始化属性和映射字段
            GetPropertyField();
            //初始化默认 sql
            var type = typeof(T);
            //初始化表名称
            _TableName = type.Name;
            var tableAttr = type.GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault();
            if (tableAttr != null)
            {
                _TableName = ((TableAttribute)tableAttr).Name;
            }

            InitSql(_TableName);
        }

        /// <summary>
        /// 初始化 基本sql
        /// </summary>
        private static void InitSql(string tableName)
        {
            var fieldNames = _DicPropertyField.Values.ToList();

            _AddSql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", tableName, string.Join(",", fieldNames.Where(s => !s.Equals(_PrimaryKey)).ToArray()), FieldNameToPropertyName(fieldNames.Where(s => !s.Equals(_PrimaryKey)).ToArray()));

            _UpdateSql = string.Format("UPDATE {0} SET {1} WHERE {2}", tableName, FieldNameEqualPropertyName(fieldNames.Where(s => !s.Equals(_PrimaryKey)).ToArray()), FieldNameEqualPropertyName(_PrimaryKey));

            _DeleteSql = string.Format("DELETE FROM {0} WHERE {1}", tableName, FieldNameEqualPropertyName(_PrimaryKey));

            _FindSql = string.Format("SELECT {0} FROM {1} WHERE {2}", FieldNameAsPropertyName(fieldNames.ToArray()), tableName, FieldNameEqualPropertyName(_PrimaryKey));

            _GetAllSql = string.Format("SELECT {0} FROM {1}", FieldNameAsPropertyName(fieldNames.ToArray()), tableName);

            _SelectFields = FieldNameAsPropertyName(fieldNames.ToArray());

        }

        /// <summary>
        /// 获取属性和字段的映射
        /// </summary>
        /// <typeparam name="T"></typeparam>
        private static void GetPropertyField()
        {
            var type = typeof(T);
            var properties = type.GetProperties();
            _Properties = properties;
            _DicPropertyField = new Dictionary<string, string>();
            _DicFieldProperty = new Dictionary<string, string>();
            foreach (PropertyInfo property in properties)
            {
                //获取 field 别名
                var fieldAttr = property.GetCustomAttributes(typeof(FieldAttribute), false).FirstOrDefault();

                var field = property.Name;
                if (fieldAttr != null)
                {
                    field = ((FieldAttribute)fieldAttr).Name;
                }
                if (!_DicPropertyField.ContainsKey(property.Name.ToUpper()))
                {
                    _DicPropertyField.Add(property.Name.ToUpper(), field.ToUpper());
                }
                if (!_DicFieldProperty.ContainsKey(field.ToUpper()))
                {
                    _DicFieldProperty.Add(field.ToUpper(), property.Name.ToUpper());
                }
                //判断获取主键
                var identityAttr = property.GetCustomAttributes(typeof(PrimaryKeyAttribute), false).FirstOrDefault();
                if (identityAttr != null) _PrimaryKey = _DicPropertyField[property.Name.ToUpper()];

            }
        }


        /// <summary>
        /// 获取真实字段并 as 为属性
        /// </summary>
        /// <param name="funcResult">接收两个参数：field , field 对应的 property,返回新的字符</param>
        /// <param name="fields">字段</param>
        /// <returns></returns>
        public static string FieldNameToPropertyName(Func<string, string, string> funcResult, params string[] fieldNames)
        {
            var result = new List<string>();
            foreach (var field in fieldNames)
            {
                if (string.IsNullOrEmpty(field)) continue;
                var tempField = field.ToUpper().Trim();
                if (_DicFieldProperty.ContainsKey(tempField))
                {
                    result.Add(funcResult(tempField, _DicFieldProperty[tempField]));
                }
                else
                {
                    result.Add(tempField);
                }
            }
            return string.Join(",", result.ToArray());
        }

        /// <summary>
        /// 获取 字段 as model的属性名
        /// </summary>
        /// <param name="fieldNames"></param>
        /// <returns></returns>
        public static string FieldNameAsPropertyName(params string[] fieldNames)
        {
            return FieldNameToPropertyName((field, property) => string.Format("{0} as {1}", field, property), fieldNames);
        }

        /// <summary>
        /// 获取 字段 =@model的属性名
        /// </summary>
        /// <param name="fieldNames"></param>
        /// <returns></returns>
        public static string FieldNameEqualPropertyName(params string[] fieldNames)
        {
            return FieldNameToPropertyName((field, property) => string.Format("{0}=@{1}", field, property), fieldNames);
        }
        /// <summary>
        /// 获取 @model属性名
        /// </summary>
        /// <param name="fieldNames"></param>
        /// <returns></returns>
        public static string FieldNameToPropertyName(params string[] fieldNames)
        {
            return FieldNameToPropertyName((field, property) => string.Format("@{0}", property), fieldNames);
        }


        /// <summary>
        /// 获取属性对应的真实字段
        /// </summary>
        /// <param name="funcResult">接收两个参数：property , property 对应的 field,返回新的字符</param>
        /// <param name="propertyNames">属性名称</param>
        /// <returns></returns>
        public static string PropertyNameToFieldName(Func<string, string, string> funcResult, params string[] propertyNames)
        {
            var result = new List<string>();
            foreach (var propertyName in propertyNames)
            {
                var tempProperty = propertyName.ToUpper().Trim();
                if (_DicPropertyField.ContainsKey(tempProperty))
                {
                    result.Add(funcResult(tempProperty, _DicPropertyField[tempProperty]));
                }
                else
                {
                    result.Add(tempProperty);
                }
            }
            return string.Join(",", result.ToArray());
        }
    }
    #region 工作单元
    /// <summary>
    /// 默认工作单元类
    /// 需要个性话的工作单元，比如使用仓储模式来调用数据的话，应自己实现接口或者使用装饰器扩展
    /// </summary>
    public class UnitWorker : IUnitWorker
    {
        private IDbTransaction dbTransaction;
        private bool isBeginTransaction;
        /// <summary>
        /// 数据链接
        /// </summary>
        public IDbConnection DbConnection { get; }
        /// <summary>
        /// 工作单元构造
        /// </summary>
        /// <param name="con">数据链接对象</param>
        /// <param name="isBeginTransaction">是否开启事务，默认自动开启，如果需要手工控制开启，则传入false</param>
        public UnitWorker(IDbConnection con, bool isBeginTransaction = true)
        {
            this.isBeginTransaction = isBeginTransaction;
            DbConnection = con ?? throw new Exception("con不能为空");
            if (isBeginTransaction) BeginTransaction();
        }
        /// <summary>
        /// 开启事务
        /// 如果初始化时默认开启事务，则无需再次开启
        /// </summary>
        public void BeginTransaction()
        {
            if (isBeginTransaction) return;
            if (DbConnection.State != ConnectionState.Open) DbConnection.Open();
            dbTransaction = DbConnection.BeginTransaction();
        }
        /// <summary>
        /// 提交事务
        /// </summary>
        public void Commit()
        {
            try
            {
                dbTransaction?.Commit();
            }
            catch (Exception)
            {
                ;
            }
        }
        /// <summary>
        /// 回滚事务
        /// </summary>
        public void Rollback()
        {
            try
            {
                dbTransaction?.Rollback();
            }
            catch (Exception)
            {
                ;
            }
        }

        public void Dispose()
        {
            if (DbConnection != null) DbConnection.Close();
        }
    }

    public static class UnitWorkerExtend
    {
        public static IUnitWorker GetUnitWorker(this IDbConnection con)
        {
            return new UnitWorker(con);
        }
    }
    #endregion


    #region 特性

    /// <summary>
    /// 描述特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Method)]
    public class DiscriptionAttribute : Attribute
    {
        /// <summary>
        /// 描述
        /// </summary>
        public string discription { get; set; }
        /// <summary>
        /// 描述
        /// </summary>
        /// <param name="discription"></param>
        public DiscriptionAttribute(string discription)
        {
            this.discription = discription;
        }
    }

    public class FieldAttribute : Attribute
    {
        public string Name { get; set; }
        public FieldAttribute(string name)
        {
            this.Name = name;
        }
    }

    /// <summary>
    /// 主键标识，标识上的字段作为主键
    /// </summary>
    public class PrimaryKeyAttribute : Attribute
    {

    }

    /// <summary>
    /// 备注
    /// </summary>
    public class RemarkAttribute : Attribute
    {
        public string remark { get; set; }

        public RemarkAttribute(string remark)
        {
            this.remark = remark;
        }
    }

    public class TableAttribute : Attribute
    {
        public string Name { get; set; }
        public TableAttribute(string name)
        {
            this.Name = name;
        }
    }
    #endregion


}
